package com.blame.javacup.simulador;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import org.javahispano.javacup.model.Tactic;

import com.blame.javacup.hortalezablamers.HortalezaBlamers;

/**
 * @author Roland Cruz bas ado en la idea original de sac astel (salim castellanos, salimsalim4< span class="java_javadoc_tag">@gmail.com)
 */
public class SimuladorTotalMain {

    private static ArrayList<Class<Tactic>> clasesTacticas = new ArrayList<Class<Tactic>>();

	public static void main(String args[]) throws Exception {

	    LinkedList<File> directorios = new LinkedList<File>();
		directorios.add(new File("build" + File.separator + "classes"));
		directorios.add(new File("bin"));
        scanForTactics(directorios);

        Vector<ResultadoDuelo> resultados = new Vector<ResultadoDuelo>();
        for(Class<Tactic> claseTactica : clasesTacticas) {
        	if(claseTactica.equals(HortalezaBlamers.class))
        		continue;
        	
        	resultados.add(SimuladorDuelo.simular(HortalezaBlamers.class, claseTactica, 100));
        }
        
        Collections.sort(resultados);
        System.out.println("fin");
	}

    /**Busca tacticas en el classpath*/
    protected static void scanForTactics(List<File> dir) {
        for (File f : dir) {
            try {
                scanDir(f);
            } catch (Exception e) {
                System.err.println("Error al scanear directorio de clases");
            }
        }
    }

    protected static void scanDir(File dir) throws Exception {
        Class[] classes = new Class[]{};
        try {
            classes = getClases(dir, "", Tactic.class, true);
        } catch (Exception e) {
            classes = new Class[]{};
        }
        for (Class c : classes) {
        	if (!c.getName().startsWith("org.javahispano.javacup.modelo.")
        			&& !c.getName().startsWith("org.javahispano.javacup.model.")
        			&& !c.getName().startsWith("org.javahispano.javacup.gui.")
        			&& !c.getName().equals("org.javahispano.javacup.tacticas_aceptadas.DaniP.Termineitor$JugadaEnsayadaAvanzayPasa")) {
        		clasesTacticas.add(c);
        	}
        }
    }
    
    /**Obtiene una lista de clases ubicadas dentro de un paquete que son asignables a una clase especifica*/
    @SuppressWarnings("unchecked")
    protected static Class[] getClases(File src, String paquete, Class claseAsignable, boolean recursivo) throws Exception {
        paquete = paquete.replace('.', '/');

        LinkedList<Class> classes = new LinkedList<Class>();
        if (!paquete.endsWith("//svn")) {
            File directory = null;
            try {
                URLClassLoader cld = URLClassLoader.newInstance(new URL[]{src.toURI().toURL()});
                if (cld == null) {
                    throw new ClassNotFoundException(
                            "Cargador de clases no encontrado.");
                }
                directory = new File(src, paquete);
                if (directory.exists()) {
                    File[] files = directory.listFiles();
                    String name, cls;
                    for (int i = 0; i < files.length; i++) {
                        name = files[i].getName();
                        if (files[i].isFile() && name.endsWith(".class")) {
                            cls = (paquete + '/' + name.substring(0, name.length() - 6)).replace('/', '.');
                            if (cls.startsWith(".")) {
                                cls = cls.substring(1);
                            }
                            Class c = cld.loadClass(cls);
                            if (!c.equals(claseAsignable) && claseAsignable.isAssignableFrom(c)) {
                                classes.add(c);
                            }
                        } else if (files[i].isDirectory()) {
                            cls = paquete + "/" + name;
                            for (Class c : getClases(src, cls, claseAsignable,
                                    recursivo)) {
                                classes.add(c);
                            }
                        }
                    }
                } else {
                    throw new ClassNotFoundException(paquete + " no es un paquete valido.");
                }
            } catch (MalformedURLException ex) {
                throw new MalformedURLException(paquete + " (" + src + ") no es una url valido.");
            } catch (NullPointerException x) {
                throw new ClassNotFoundException(paquete + " (" + directory + ") no es un paquete valido.");
            }
        }
        Class[] classesA = new Class[classes.size()];
        classes.toArray(classesA);
        return classesA;
    }

}